Symbol 笔记
Symbol
Symbol 是 es 新的数据类型,最基本的功能就是生成一个唯一值。
例如:
Symbol() === Symbol(); // false
Symbol("foo") === Symbol("foo"); // false
Symbol({}) === Symbol({}); // false
Symbol 特性
-
Symbol 函数不能使用 new 关键字实例化
-
Symbol 类型转换
-
typeof
关键字验证 Symbol 类型总是返回"symbol"
-
Symbol 值隐式转换数字或者字符串会报错,例如:
+Symbol(); // error Symbol() + ""; //error
-
宽松相等时,
Object(sym) == sym
返回 true -
Symbol 值可以显式转化为字符串,使用
String(sym)
类似于sym.toString()
-
-
for…in 语句不会遍历对象的 Symbol 键:
const foo = { [Symbol()]: "any", bar: "bar value", }; for (const item in foo) { console.log(item); // only "bar" }
但是可以使用 Object.getOwnPropertySymbols() 来获取对象的 Symbol 键。
-
JSON.stringify 不会序列化 Symbol 键:
const foo = { [Symbol()]: "any", }; JSON.stringify(foo); // "{}"
方法(部分)
所有方法详见。
Symbol.for(key)
因为 Symbol 生成的值是唯一的,所以在 es 模块系统中无法正常共享数据,但是 Symbol 提供两个方法来共享全局的 Symbol。
Symbol.for 使用给定的 key 一个字符串在全局注册一个 Symbol 值并返回对应的 Symbol,如果该 key 已经注册,则返回对应的 Symbol。
Symbol.keyFor(sym)
同 Symbol.for 功能相反,通过 Symbol 查找其在全局上注册的 key 值。
使用:
const globalSym = Symbol.for("global");
const globalSym2 = Symbol.for("global");
globalSym === globalSym2; // true
Symbol.keyFor(globalSym); // "global"
属性(部分)
所有属性详见。
Symbol.hasInstance
Symbol.hasInstance 用于判断某对象是否为某构造器的实例。
它可以被用来自定义 instanceof 行为:
class NullObj {
static [Symbol.hasInstance](instance) {
return instance === null;
}
}
console.log(null instanceof NullObj); // true
Symbol.iterator
Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器可以被 for…of 循环使用。
例如:
Number.prototype[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
console.log([...NaN]); // [1,2,3]
Symbol 还提供另一个属性模拟异步迭代器 Symbol.asyncIterator
Symbol.toPrimitive
Symbol.toPrimitive 是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,当一个对象转换为对应的原始值时,会调用此函数。
Symbol.toPrimitive 会改变对象转化为原始值的默认行为。例如:
const object1 = {
[Symbol.toPrimitive](hint) {
return "hello world";
},
};
console.log(object1 + "!"); // "hello world!"
上述 object1 + "!"
表达式对 object1 进行了隐式转化,调用了 Symbol.toPrimitive 属性的函数。
这里 有更有趣的玩法。
Symbol.toStringTag
Symbol.toStringTag 是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString() 方法会去读取这个标签并把它包含在自己的返回值里。
例如:
class ValidatorClass {
get [Symbol.toStringTag]() {
return "Validator";
}
}
Object.prototype.toString.call(new ValidatorClass()); // "[object Validator]"
或者改变原始类:
Object.defineProperty(Number.prototype, Symbol.toStringTag, {
get() {
return "Not a number";
},
});
Object.prototype.toString.call(1); // '[object Not a number]'